using QQZiFramework;
using QQZiFramework.Membership;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net.Repository;
using log4net;
using System.IO;
using Newtonsoft.Json.Linq;

namespace DemoConsole
{
    /// <summary>
    /// 线程或者后台服务用，可手动设置登录用户
    /// </summary>
    public class HandlerMemberShip : CommonMemberShip
    {
        public static string rootPath;
        QQZiFramework.Membership.BaseUser LoginUser;

        public static string configDicName = "QQZiCore.App"; 

        static HandlerMemberShip()
        {
            System.IO.DirectoryInfo directory = new DirectoryInfo(Directory.GetCurrentDirectory());
            while (true)
            {
                if (directory.Name == "bin" || directory.Name == "Debug" || directory.Name.StartsWith("netcore"))
                {
                    directory = directory.Parent;
                }
                else
                {
                    break;
                }
            }
            rootPath = directory.FullName;
        }
        public override QQZiFramework.Membership.LoginUserStateType UserStateType
        {
            get
            {
                return QQZiFramework.Membership.LoginUserStateType.Static;
            }
        }

        public override string MessageAsyncPath
        {
            get { return "Public/TriggerMessageSent"; }
        }

        public override BaseUser GetUserFrom(DBContext context)
        {
            return LoginUser;
        }

    static string strToken;

       public override TokenInfo GetTokenInfo(DBContext context)
        {
           
            if (strToken == null) return null;
            string key = "login_" + strToken;
            string json = context.GetRedisDatabase(GetLoginStateDBIndex(context)).GetRedisItem<string>(key, false);
            if (json == null) return null;
            JToken jToken = Newtonsoft.Json.Linq.JToken.Parse(json);
            TokenInfo tokenInfo = new TokenInfo();
            tokenInfo.ExpiresAt = jToken.Value<string>("ExpiresAt");
            tokenInfo.Token = jToken.Value<string>("Token");
            int platform = jToken.Value<int>("PlatfromId");
            if (platform == 0) platform = 1;
            tokenInfo.PlatfromId = (LoginPlatfromId)platform;
            tokenInfo.UserId = jToken.Value<int>("UserId");
            tokenInfo.AppSecret = jToken.Value<string>("AppSecret");
            tokenInfo.ValueTypeName = jToken.Value<string>("ValueTypeName");
            if (jToken["Values"].HasValues && tokenInfo.ValueTypeName != null)
            {
                tokenInfo.Values = jToken["Values"].ToObject(Type.GetType(tokenInfo.ValueTypeName));
            }
            return tokenInfo;
        }

        public override Type UserType
        {
            get { return typeof(QQZiFramework.Membership.BaseUser); }
        }

       
       

        protected int GetLoginStateDBIndex(DBContext context){
            
            return context.GetSettingValue<int>("Redis:Login",false,DBContext.Default_Redis_Database_Index);
            
        }
         public override BaseUser GetRedisUser(int userId, DBContext context)
        {
            if (!DBContext.UserRedis) throw new Exception("需要配置redis使用！");
            string key = "User_" + userId;
            int dbIndex = GetLoginStateDBIndex(context);
            string userJson = context.GetRedisDatabase(dbIndex).GetRedisItem<string>(key, false);
            // User u = context.GetRedisItem<User>(key, false);
            IDBEntity user;
            if (userJson == null)
            {
                QueryParam param = new QueryParam() { entityType = UserType};       
                param.AddWhere("UserId", userId.ToString());
                user = context.DoGetOne(param, "找不到用户" + userId);
                // u = context.QuerySingle<User>(null, userId, null, MemberShip.User_NoFound_ErrorMsg, false);
                context.SetRedisItem(key, userJson);
            }
            else user = (IDBEntity)Newtonsoft.Json.JsonConvert.DeserializeObject(userJson, UserType);
            return user as BaseUser;
        }
 

        public override DBContext CreateDBContext()
        {
            System.Collections.Hashtable args = new System.Collections.Hashtable();
            return new DBContext(null, null, null, this, args);
        }

        /// <summary>
        /// 保存用户信息到cookie或者session
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="Expires">超时时间</param>
        /// <returns>TokenInfo,0:返回Token供客户端（比如app），1：appSecret</returns>
        public override TokenInfo SetUserLoginState(BaseUser userInfo, LoginUserStateType userStateType, DateTime Expires, LoginPlatfromId platForm, object extValues, DBContext context)
        {
            userInfo.LastLoginTime = DateTime.Now;
            if (userInfo == null) throw new ClientException("RecordLogin exception , userinfo is null");
            string appSecret = Guid.NewGuid().ToString();
            TokenInfo tokenInfo = new TokenInfo { PlatfromId = platForm, AppSecret = appSecret, Values = extValues, UserId = userInfo.UserId };
            tokenInfo.ExpiresAt = Expires.ToString("yyyy-MM-dd HH:mm:ss");
            switch (userStateType)
            {

                case LoginUserStateType.Redis:
                    tokenInfo.Token =strToken= QQZiFramework.Utility.EncryptMD5(userInfo.UserId + "_" + userInfo.LastLoginTime.ToString("yyyyMMddHHmmss")) + QQZiFramework.Utility.EncryptNumber(userInfo.UserId);
                    string redisVal = Newtonsoft.Json.JsonConvert.SerializeObject(tokenInfo);
                    int dbIndex = GetLoginStateDBIndex(context);
                    context.GetRedisDatabase(dbIndex).SetRedisItem("login_" + tokenInfo.Token, redisVal, Expires);
                    break;
                default:
                    break;
            }
            return tokenInfo;
        }

     


        public string GetRequestHeader(string name)
        {
            return null;
        }


        public override void OnDBContextInit(DBContext context)
        {
            context.SetArgument("IsMobileDevice", false);
        }

       

 
        public override bool IsDevelopment()
        {
            return true;
        }

        public static ILoggerRepository repository;

        public ILoggerRepository GetLogRepository()
        {
            if (repository != null) return repository;
            String logConfigPath = Path.Combine(rootPath, "log4net.config");
            FileInfo logFile = new FileInfo(logConfigPath);
            if (logFile.Exists)
            {
                repository = LogManager.CreateRepository("NETCoreRepository");
                log4net.Config.XmlConfigurator.Configure(repository, logFile);
            }
            else
            {
                throw new FileNotFoundException(logConfigPath);
            }
            return repository;
        }

        /// <summary>
        /// 日志记录
        /// </summary>       
        public override void LogMessage(string message, string appendMsg, DBContext context)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(GetLogRepository().Name, appendMsg == null ? "system" : appendMsg);
            log.Info(message);
            System.Diagnostics.Debug.WriteLine(message);
        }

        /// <summary>
        /// 异常日志记录
        /// </summary>  
        public override void LogException(Exception ex, string appendMsg, DBContext context)
        {

            log4net.ILog log = log4net.LogManager.GetLogger(GetLogRepository().Name, appendMsg == null ? "system" : appendMsg);
            if (ex != null)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                log.Error(ex.Message, ex);
            }
            else log.Error(appendMsg);
        }
        static Newtonsoft.Json.Linq.JToken token;

        public static Newtonsoft.Json.Linq.JToken GetStttingToken()
        {
            if (token == null)
            {
                var rootPath = HandlerMemberShip.rootPath;
                string appSettingFile = Path.Combine(rootPath, "appsettings.json");
                using (System.IO.StreamReader file = new StreamReader(appSettingFile, System.Text.Encoding.UTF8))
                {
                    string json = file.ReadToEnd();
                    token = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.Parse(json);
                }
            }
            return token;
        }
        public override T GetSettingValue<T>(DBContext context, string path, bool throwNoFoundError = false, T defaultVal = default(T))
        {
            GetStttingToken();
            string[] pathArr = path.Split(':');
            for (int i = 0; i < pathArr.Length - 1; i++)
            {
                token = token[pathArr[i]];
                if (token == null) return defaultVal;
            }
            string keyName = pathArr[pathArr.Length - 1];
            if (token[keyName] == null)
            {
                return defaultVal;
            }
            else
            {
                if (token[keyName] != null && token[keyName].HasValues)
                {
                    //如果读取的结点是对象（还有下级节点）
                    return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(token[keyName].ToString());
                }
                else
                {
                    return token.Value<T>(keyName);
                }
            }
        }

        public override void ClearCache(DBContext context)
        {
            queryMapping = null;
        }

        public static Dictionary<string, QueryEntityConfig> queryMapping;

        /// <summary>
        /// Permission文件的内容
        /// </summary>  
        public override Dictionary<string, QueryEntityConfig> GetPermissionQueryMapping(DBContext context)
        {
            if (queryMapping != null) return queryMapping;
            var path = HandlerMemberShip.rootPath;
            String filePath = Path.Combine(path, "Permission.json");
            string json = QQZiFramework.Utility.ReadFile(filePath);
            if (string.IsNullOrEmpty(json)) queryMapping = new Dictionary<string, QueryEntityConfig>();
            else queryMapping = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, QueryEntityConfig>>(json);
            return queryMapping;
        }

        public override string UserToCookie(BaseUser u)
        {
            throw new NotImplementedException();
        }

        public override BaseUser GetCookieUser(string cookieValue)
        {
            throw new NotImplementedException();
        }

        public override string GetRequestHeader(DBContext context, string name)
        {
            throw new NotImplementedException();
        }

        public override void LogDebug(string message,string module, DBContext context)
        {
            System.Diagnostics.Debug.WriteLine(message);
        }
    }
}
